using UnityEngine;
using System.Collections;

public class SphereScript : MonoBehaviour {
	public const float gravity = 40.0f;
	public const float hindrance = 20.0f;
	public const float moveTime = 0.3f;
	public enum SphereState
	{
		State_None,
		State_Idle,
		State_Move,
		State_FallDown,
		State_Destroy,
		State_Num,
	}
	
	public class SphereEvent: System.EventArgs
	{
		public Vector3 moveTo;
	}

	// Use this for initialization
	void Start () {
		
		if ( renderer )
		{
			renderer.material.color = sphereColor;
		}
		
	}
	
	public void Init()
	{
		InitMechanic();
	}
	
	// Update is called once per frame
	void Update () {
	
	}
	
	void OnDestroy() {
        print("Script was destroyed");
    }
	
	public void SetSphereType( GameMsgScript.SphereType tyoe, Color color )
	{
		sphereType = tyoe;
		sphereColor = color;
	}
	
	public void InitMechanic()
	{
		stateMechanics[(int)SphereState.State_Idle] = new StateMechanicScript( (int)SphereState.State_Num,
			SwitchToIdle, BreakIdle );
		stateMechanics[ (int)SphereState.State_Idle ].SetStateChange( (int)SphereState.State_FallDown, true );
		stateMechanics[ (int)SphereState.State_Idle ].SetStateChange( (int)SphereState.State_Move, true );
		
		stateMechanics[(int)SphereState.State_FallDown] = new StateMechanicScript( (int)SphereState.State_Num,
			SwitchToFallDown, BreakFallDown );
		stateMechanics[(int)SphereState.State_FallDown].SetStateChange( (int)SphereState.State_Destroy, true );
		
		stateMechanics[(int)SphereState.State_Destroy] = new StateMechanicScript( (int)SphereState.State_Num,
			SwitchToDestroy, null );
		
		stateMechanics[(int)SphereState.State_Move] = new StateMechanicScript( (int)SphereState.State_Num,
			SwitchToMove, BreakMove );
		stateMechanics[(int)SphereState.State_Move].SetStateChange( (int)SphereState.State_Destroy, true );
		stateMechanics[(int)SphereState.State_Move].SetStateChange( (int)SphereState.State_Idle, true );
			
	}
	
	public bool SwithState( SphereState changeToState, System.EventArgs e )
	{
		if ( stateMechanics[ (int)curState ].CanChangeTo( (int)changeToState ) )
		{
			stateMechanics[ (int)curState ].breakFunction( this, e );
			stateMechanics[ (int)changeToState ].stateFunction( this, e );
			return true;
		}
		return false;
	}
	
				
	public void SwitchToIdle(  object sender, System.EventArgs e )
	{
		curState = SphereScript.SphereState.State_Idle;
	}
	
	public void BreakIdle(   object sender, System.EventArgs e )
	{
	}
	
	public void SwitchToFallDown(  object sender, System.EventArgs e )
	{
		transform.position -= Vector3.forward * 2;
		curState = SphereScript.SphereState.State_FallDown;
		curSpeed = Random.insideUnitSphere * 10.0f;
		curSpeed.z = 0;
		if ( curSpeed.y < 0 )
		{
			curSpeed.y = -curSpeed.y;
		}
		
		direction = -Mathf.Sign( curSpeed.x );
		
		StartCoroutine( "FallDown" );
	}
	
	public void BreakFallDown(   object sender, System.EventArgs e )
	{
	}
	
	protected IEnumerator FallDown()
	{
		while( true )
		{
			transform.position += curSpeed * Time.deltaTime;
			
			yield return null;
			
			curSpeed.y -= gravity * Time.deltaTime;
			
			if ( curSpeed.x != 0 )
			{
				 curSpeed.x += direction * hindrance * Time.deltaTime;
				 if ( Mathf.Sign( curSpeed.x ) == direction )
					curSpeed.x = 0;
			}
			
			if ( !renderer.isVisible )	
				break;
		}
		
		SwithState( SphereState.State_Destroy, null );
		
	}
	
	public IEnumerator MoveTo()
	{
		while ( Time.time - startMoveTime < moveTime )
		{
			transform.position = 
				Vector3.Lerp( sourcePosition, targetPosition, (Time.time - startMoveTime) / moveTime );
			yield return null;
		}
		yield return null;
		transform.position = targetPosition;
		if ( parent != null	)
			SwithState( SphereState.State_Idle, null );
		else
			SwithState( SphereState.State_Destroy, null );
	}
	
	public void  SwitchToDestroy(   object sender, System.EventArgs e )
	{
		DestroyImmediate(gameObject);
		//Destroy( this );
	}
	
	public void SwitchToMove(  object sender, System.EventArgs e )
	{
		SphereEvent se = e as SphereEvent;
		curState = SphereScript.SphereState.State_Move;
		startMoveTime = Time.time;
		targetPosition = se.moveTo;
		sourcePosition = transform.position;
		StartCoroutine("MoveTo");
	}
	
	public void BreakMove(   object sender, System.EventArgs e )
	{
	}
	
	
	
	
	public ScreenMsgScript.ScreenNode parent;
	public GameMsgScript.SphereType sphereType = GameMsgScript.SphereType.Type_Red;
	public Color	sphereColor;
	
	public StateMechanicScript[] stateMechanics = new StateMechanicScript[(int)SphereState.State_Num];
	public SphereState curState = SphereScript.SphereState.State_Idle;
	
	public Vector3 curSpeed =  Vector3.zero;
	public float direction = 0;
	
	
	public Vector3 sourcePosition =  Vector3.zero;
	public Vector3 targetPosition =  Vector3.zero;
	
	public float   startMoveTime;
	
}
